home *** CD-ROM | disk | FTP | other *** search
- /* DriverPrepMemoryInit.c */
- /*
- * DriverPrepMemoryInit.c
- * Copyright © 1994-95 Apple Computer Inc. All rights reserved.
- *
- * .
- */
- /* .___________________________________________________________________________________.
- | Initialize the permanent memory areas that are shared between the driver and the |
- | NCR card: the SCSI script and the per-request record. If this is extended to |
- | support concurrent I/O (i.e. to support SCSI suspend/resume), we must create and |
- | prepare several per-request records. When an application calls PBRead or PBWrite, |
- | a separate, more complex, function will handle preparation of the actual I/O |
- | buffer.
- .___________________________________________________________________________________.
- */
- #include "NCRDriverPrivate.h"
-
- /*
- * Create an I/O Preparation table for the global script. This is created once, when
- * the driver starts. The NCR chip reads the script asynchronously. This function
- * may serve as an example for a general global shared area.
- */
- OSErr
- PrepareMemoryForScript(
- AddressSpaceID addressSpaceID
- )
- {
- OSErr status;
- ItemCount mapEntriesNeeded;
-
- Trace(PrepareMemoryForScript);
- GLOBAL.scriptIOTable.options =
- ( (0 * kIOIsInput) /* Chip won't write script */
- | (1 * kIOIsOutput) /* Chip reads the script */
- | (0 * kIOMultipleRanges) /* No scatter-gather list */
- | (1 * kIOLogicalRanges) /* Logical addresses */
- | (0 * kIOMinimalLogicalMapping) /* Normal logical mapping */
- | (1 * kIOShareMappingTables) /* Share with Kernel */
- | (0 * kIOCoherentDataPath) /* No fancy data path */
- );
- GLOBAL.scriptIOTable.addressSpace = addressSpaceID;
- GLOBAL.scriptIOTable.firstPrepared = 0;
- GLOBAL.scriptIOTable.logicalMapping = NULL;
- GLOBAL.scriptIOTable.rangeInfo.range.base = (LogicalAddress) gNCRSCSIScript;
- GLOBAL.scriptIOTable.rangeInfo.range.length = gNCRSCSIScriptSize;
- mapEntriesNeeded = GetMapEntryCount(gNCRSCSIScript, gNCRSCSIScriptSize);
- GLOBAL.scriptIOTable.mappingEntryCount = mapEntriesNeeded;
- GLOBAL.scriptIOTable.physicalMapping = PoolAllocateResident(
- mapEntriesNeeded * sizeof (PhysicalAddress),
- TRUE
- );
- status = (GLOBAL.scriptIOTable.physicalMapping != NULL) ? noErr : memFullErr;
- CheckStatus(status, "\pAllocate Script PhysicalMapping");
- if (status == noErr) {
- status = PrepareMemoryForIO(&GLOBAL.scriptIOTable);
- CheckStatus(status, "\pPrepareMemory for Script");
- }
- if (status == noErr)
- status = CheckForContiguousPhysicalMapping(&GLOBAL.scriptIOTable);
- if (status != noErr)
- PublishInitFailureMsg(status, "\pPrepareMemoryForScript failed");
- return (status);
- }
-
- /*
- * Dispose of the script I/O preparation table. This is called when the driver stops.
- */
- void
- DisposeMemoryForScript(void)
- {
- Trace(DisposeMemoryForScript);
- CheckpointIOTable(&GLOBAL.scriptIOTable);
- if (GLOBAL.scriptIOTable.physicalMapping != NULL)
- (void) PoolDeallocate(GLOBAL.scriptIOTable.physicalMapping);
- CLEAR(GLOBAL.scriptIOTable);
- }
-
- /*
- * Create a PerRequest record and its I/O Preparation table. To create the table, we
- * must first determine the number of physical mapping table entries we will need for
- * the user I/O request and the PerRequestRecord itself.
- *
- * This is called when the driver starts. If we support concurrent I/O, we create
- * several of these records. The per-request record is a small amount of memory that
- * is shared between the NCR card and the driver.
- */
- OSErr
- CreatePerRequestRecord(
- AddressSpaceID addressSpaceID
- )
- {
- OSErr status;
- OSStatus osStatus;
- PerRequestDataPtr perRequestDataPtr;
- ItemCount requestMapEntries; /* PerRequestData only */
- ByteCount mapTableSize;
- #define REQUEST (*perRequestDataPtr)
-
- Trace(CreatePerRequestRecord);
- perRequestDataPtr = (PerRequestDataPtr)
- MemAllocatePhysicallyContiguous(sizeof (PerRequestData), TRUE);
- status = (perRequestDataPtr != NULL) ? noErr : memFullErr;
- CheckStatus(status, "\pAllocate PerRequestRecord");
- if (status == noErr) {
- /*
- * PrepareNextDMATransfer will be called (as a Software Task) to prepare
- * a subsequent "chunk" of DMA if the original preparation is incomplete.
- */
- osStatus = CreateSoftwareInterrupt(
- PrepareNextDMATask, /* Handler function */
- CurrentTaskID(), /* For my driver task */
- perRequestDataPtr, /* Handler parameter */
- TRUE, /* Persistant */
- &REQUEST.nextDMAInterruptID /* Result */
- );
- CheckStatus(osStatus, "\pCreateSoftwareInterrupt");
- }
- if (status == noErr) {
- GLOBAL.perRequestDataPtr = perRequestDataPtr;
- /*
- * Allocate a maximum-length physical mapping table that will be used for
- * each user I/O request. By passing a dummy value that happens to fall
- * at the end of the page, we'll get the as many entries as we need.
- */
- REQUEST.scsiMapEntries = GetMapEntryCount(
- (void *) (GLOBAL.pageSize - 1), kNCRDriverMaxTransfer);
- requestMapEntries = GetMapEntryCount(perRequestDataPtr, sizeof (PerRequestData));
- mapTableSize = (REQUEST.scsiMapEntries + requestMapEntries)
- * sizeof (PhysicalAddress);
- REQUEST.physicalMapTables = PoolAllocateResident(mapTableSize, TRUE);
- /*
- * Initialize the constant part of the PerRequest mapping table. We leave
- * this prepared "forever" for now. In the future, we may checkpoint it
- * so it is only prepared while an I/O request is active.
- */
- REQUEST.perRequestIOTable.options =
- ( (0 * kIOIsInput) /* These will be set by */
- | (0 * kIOIsOutput) /* calling CheckpointIO */
- | (0 * kIOMultipleRanges) /* No scatter-gather list */
- | (1 * kIOLogicalRanges) /* Logical addresses */
- | (0 * kIOMinimalLogicalMapping) /* Normal logical mapping */
- | (1 * kIOShareMappingTables) /* Share with Kernel */
- | (0 * kIOCoherentDataPath) /* No fancy data path */
- );
- REQUEST.perRequestIOTable.addressSpace = addressSpaceID;
- REQUEST.perRequestIOTable.firstPrepared = 0;
- REQUEST.perRequestIOTable.logicalMapping = NULL;
- REQUEST.perRequestIOTable.rangeInfo.range.base = perRequestDataPtr;
- REQUEST.perRequestIOTable.rangeInfo.range.length = sizeof (PerRequestData);
- REQUEST.perRequestIOTable.physicalMapping =
- &REQUEST.physicalMapTables[REQUEST.scsiMapEntries];
- REQUEST.perRequestIOTable.mappingEntryCount = requestMapEntries;
- /*
- * Note that the PerRequestData record is prepared once, and checkpointed
- * before and after each transaction -- kMoreTransfers will be used so
- * that system resources are not released.
- */
- status = PrepareMemoryForIO(&REQUEST.perRequestIOTable);
- CheckStatus(status, "\pPrepareMemoryForIO perRequest");
- }
- if (status != noErr)
- DisposePerRequestRecord(&GLOBAL.perRequestDataPtr);
- if (status != noErr)
- PublishInitFailureMsg(status, "\pPrepareMemoryForScript failed");
- return (status);
- #undef REQUEST
- }
-
- /*
- * This is called when the driver is finalized.
- */
- void
- DisposePerRequestRecord(
- PerRequestDataPtr *perRequestPtrAddr
- )
- {
- PerRequestDataPtr perRequestDataPtr;
- #define REQUEST (*perRequestDataPtr)
-
- Trace(DisposePerRequestRecord);
- while ((perRequestDataPtr = *perRequestPtrAddr) != NULL) {
- if (CompareAndSwap(
- (UInt32) perRequestDataPtr, NULL, (UInt32 *) perRequestPtrAddr)) {
- CheckpointIOTable(&REQUEST.scsiIOTable);
- CheckpointIOTable(&REQUEST.perRequestIOTable);
- if (REQUEST.nextDMAInterruptID != kInvalidID)
- (void) DeleteSoftwareInterrupt(REQUEST.nextDMAInterruptID);
- if (REQUEST.physicalMapTables != NULL)
- (void) PoolDeallocate(REQUEST.physicalMapTables);
- (void) PoolDeallocate(perRequestDataPtr);
- }
- }
- #undef REQUEST
- }
-
-